home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Environments
/
PowerLisp 2.01
/
Supplemental Documentation
/
Documentation
/
Chapter 10. Symbols
< prev
next >
Wrap
Text File
|
1995-03-27
|
21KB
|
481 lines
Common Lisp the Language, 2nd Edition
-------------------------------------------------------------------------------
10. Symbols
A Lisp symbol is a data object that has three user-visible components:
* The property list is a list that effectively provides each symbol with
many modifiable named components.
* The print name must be a string, which is the sequence of characters used
to identify the symbol. Symbols are of great use because a symbol can be
located once its name is given (typed, say, on a keyboard). One may
ordinarily not alter a symbol's print name.
[change_begin]
X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to specify it is an error to
alter a print name.
[change_end]
* The package cell must refer to a package object. A package is a data
structure used to locate a symbol once given the symbol's name. A symbol
is uniquely identified by its name only when considered relative to a
package. A symbol may appear in many packages, but it can be owned by at
most one package. The package cell points to the owner, if any. Package
cells are discussed along with packages in chapter 11.
A symbol may actually have other components for use by the implementation. One
of the more important uses of symbols is as names for program variables; it is
frequently desirable for the implementor to use certain components of a symbol
to implement the semantics of variables. See symbol-value and symbol-function.
However, there are several possible implementation strategies, and so such
possible components are not described here.
-------------------------------------------------------------------------------
* The Property List
* The Print Name
* Creating Symbols
-------------------------------------------------------------------------------
10.1. The Property List
Since its inception, Lisp has associated with each symbol a kind of tabular
data structure called a property list (plist for short). A property list
contains zero or more entries; each entry associates with a key (called the
indicator), which is typically a symbol, an arbitrary Lisp object (called the
value or, sometimes, the property). There are no duplications among the
indicators; a property list may only have one property at a time with a given
name. In this way, given a symbol and an indicator (another symbol), an
associated value can be retrieved.
A property list is very similar in purpose to an association list. The
difference is that a property list is an object with a unique identity; the
operations for adding and removing property-list entries are destructive
operations that alter the property list rather than making a new one.
Association lists, on the other hand, are normally augmented non-destructively
(without side effects) by adding new entries to the front (see acons and
pairlis).
A property list is implemented as a memory cell containing a list with an even
number (possibly zero) of elements. (Usually this memory cell is the
property-list cell of a symbol, but any memory cell acceptable to setf can be
used if getf and remf are used.) Each pair of elements in the list constitutes
an entry; the first item is the indicator, and the second is the value. Because
property-list functions are given the symbol and not the list itself,
modifications to the property list can be recorded by storing back into the
property-list cell of the symbol.
When a symbol is created, its property list is initially empty. Properties are
created by using get within a setf form.
Common Lisp does not use a symbol's property list as extensively as earlier
Lisp implementations did. Less-used data, such as compiler, debugging, and
documentation information, is kept on property lists in Common Lisp.
-------------------------------------------------------------------------------
Compatibility note: In older Lisp implementations, the print name, value, and
function definition of a symbol were kept on its property list. The value cell
was introduced into MacLisp and Interlisp to speed up access to variables;
similarly for the print-name cell and function cell (MacLisp does not use a
function cell). Recent Lisp implementations such as Spice Lisp, Lisp Machine
Lisp, and NIL have introduced all of these cells plus the package cell. None of
the MacLisp system property names (expr, fexpr, macro, array, subr, lsubr,
fsubr, and in former times value and pname) exist in Common Lisp.
In Common Lisp, the notion of ``disembodied property list'' introduced in
MacLisp is eliminated. It tended to be used for rather kludgy things, and in
Lisp Machine Lisp is often associated with the use of locatives (to make it
``off by one'' for searching alternating keyword lists). In Common Lisp special
setf-like property-list functions are introduced: getf and remf.
-------------------------------------------------------------------------------
[Function]
get symbol indicator &optional default
get searches the property list of symbol for an indicator eq to indicator. The
first argument must be a symbol. If one is found, then the corresponding value
is returned; otherwise default is returned.
If default is not specified, then nil is used for default.
Note that there is no way to distinguish an absent property from one whose
value is default.
(get x y) == (getf (symbol-plist x) y)
Suppose that the property list of foo is (bar t baz 3 hunoz "Huh?"). Then, for
example:
(get 'foo 'baz) => 3
(get 'foo 'hunoz) => "Huh?"
(get 'foo 'zoo) => nil
-------------------------------------------------------------------------------
Compatibility note: In MacLisp, the first argument to get could be a list, in
which case the cdr of the list was treated as a so-called ``disembodied
property list.'' The first argument to get could also be any other object, in
which case get would always return nil. In Common Lisp, it is an error to give
anything but a symbol as the first argument to get.
What Common Lisp calls get, Interlisp calls getprop.
What MacLisp and Interlisp call putprop is accomplished in Common Lisp by using
get with setf.
-------------------------------------------------------------------------------
setf may be used with get to create a new property-value pair, possibly
replacing an old pair with the same property name. For example:
(get 'clyde 'species) => nil
(setf (get 'clyde 'species) 'elephant) => elephant
and now (get 'clyde 'species) => elephant
The default argument may be specified to get in this context; it is ignored by
setf but may be useful in such macros as push that are related to setf:
(push item (get sym 'token-stack '(initial-item)))
means approximately the same as
(setf (get sym 'token-stack '(initial-item))
(cons item (get sym 'token-stack '(initial-item))))
which in turn would be treated as simply
(setf (get sym 'token-stack)
(cons item (get sym 'token-stack '(initial-item))))
[change_begin]
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
permissible side effects of certain operations; (setf (get symbol indicator)
newvalue) is required to behave exactly the same as (setf (getf (symbol-plist
symbol) indicator) newvalue).
[change_end]
[Function]
remprop symbol indicator
This removes from symbol the property with an indicator eq to indicator. The
property indicator and the corresponding value are removed by destructively
splicing the property list. It returns nil if no such property was found, or
non-nil if a property was found.
(remprop x y) == (remf (symbol-plist x) y)
For example, if the property list of foo is initially
(color blue height 6.3 near-to bar)
then the call
(remprop 'foo 'height)
returns a non-nil value after altering foo's property list to be
(color blue near-to bar)
[change_begin]
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
permissible side effects of certain operations; (remprop symbol indicator) is
required to behave exactly the same as (remf (symbol-plist symbol) indicator).
[change_end]
[Function]
symbol-plist symbol
This returns the list that contains the property pairs of symbol; the contents
of the property-list cell are extracted and returned.
Note that using get on the result of symbol-plist does not work. One must give
the symbol itself to get or else use the function getf.
setf may be used with symbol-plist to destructively replace the entire property
list of a symbol. This is a relatively dangerous operation, as it may destroy
important information that the implementation may happen to store in property
lists. Also, care must be taken that the new property list is in fact a list of
even length.
-------------------------------------------------------------------------------
Compatibility note: In MacLisp, this function is called plist; in Interlisp, it
is called getproplist.
-------------------------------------------------------------------------------
[Function]
getf place indicator &optional default
getf searches the property list stored in place for an indicator eq to
indicator. If one is found, then the corresponding value is returned; otherwise
default is returned. If default is not specified, then nil is used for default.
Note that there is no way to distinguish an absent property from one whose
value is default. Often place is computed from a generalized variable
acceptable to setf.
setf may be used with getf, in which case the place must indeed be acceptable
as a place to setf. The effect is to add a new property-value pair, or update
an existing pair, in the property list kept in the place. The default argument
may be specified to getf in this context; it is ignored by setf but may be
useful in such macros as push that are related to setf. See the description of
get for an example of this.
[change_begin]
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
permissible side effects of certain operations; setf used with getf is
permitted to perform a setf on the place or on any part, car or cdr, of the
top-level list structure held by that place.
X3J13 voted in March 1988 (PUSH-EVALUATION-ORDER) to clarify order of
evaluation (see section 7.2).
[change_end]
-------------------------------------------------------------------------------
Compatibility note: The Interlisp function listget is similar to getf. The
Interlisp function listput is similar to using getf with setf.
-------------------------------------------------------------------------------
[Macro]
remf place indicator
This removes from the property list stored in place the property with an
indicator eq to indicator. The property indicator and the corresponding value
are removed by destructively splicing the property list. remf returns nil if no
such property was found, or some non-nil value if a property was found. The
form place may be any generalized variable acceptable to setf. See remprop.
[change_begin]
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
permissible side effects of certain operations; remf is permitted to perform a
setf on the place or on any part, car or cdr, of the top-level list structure
held by that place.
X3J13 voted in March 1988 (PUSH-EVALUATION-ORDER) to clarify order of
evaluation (see section 7.2).
[change_end]
[Function]
get-properties place indicator-list
get-properties is like getf, except that the second argument is a list of
indicators. get-properties searches the property list stored in place for any
of the indicators in indicator-list until it finds the first property in the
property list whose indicator is one of the elements of indicator-list.
Normally place is computed from a generalized variable acceptable to setf.
get-properties returns three values. If any property was found, then the first
two values are the indicator and value for the first property whose indicator
was in indicator-list, and the third is that tail of the property list whose
car was the indicator (and whose cadr is therefore the value). If no property
was found, all three values are nil. Thus the third value serves as a flag
indicating success or failure and also allows the search to be restarted, if
desired, after the property was found.
-------------------------------------------------------------------------------
10.2. The Print Name
Every symbol has an associated string called the print name. This string is
used as the external representation of the symbol: if the characters in the
string are typed in to read (with suitable escape conventions for certain
characters), it is interpreted as a reference to that symbol (if it is
interned); and if the symbol is printed, print types out the print name. For
more information, see the sections on the reader (section 22.1.1) and printer
(section 22.1.6).
[Function]
symbol-name sym
This returns the print name of the symbol sym. For example:
(symbol-name 'xyz) => "XYZ"
It is an extremely bad idea to modify a string being used as the print name of
a symbol. Such a modification may tremendously confuse the function read and
the package system.
[change_begin]
X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to specify that it is an error
to modify a string being used as the print name of a symbol.
[change_end]
-------------------------------------------------------------------------------
10.3. Creating Symbols
Symbols can be used in two rather different ways. An interned symbol is one
that is indexed by its print name in a catalogue called a package. A request to
locate a symbol with that print name results in the same (eq) symbol. Every
time input is read with the function read, and that print name appears, it is
read as the same symbol. This property of symbols makes them appropriate to use
as names for things and as hooks on which to hang permanent data objects (using
the property list, for example).
Interned symbols are normally created automatically; the first time something
(such as the function read) asks the package system for a symbol with a given
print name, that symbol is automatically created. The function used to ask for
an interned symbol is intern, or one of the functions related to intern.
Although interned symbols are the most commonly used, they will not be
discussed further here. For more information, see chapter 11.
An uninterned symbol is a symbol used simply as a data object, with no special
cataloguing (it belongs to no particular package). An uninterned symbol is
printed as #: followed by its print name. The following are some functions for
creating uninterned symbols.
[Function]
make-symbol print-name
(make-symbol print-name) creates a new uninterned symbol, whose print name is
the string print-name. The value and function bindings will be unbound and the
property list will be empty.
The string actually installed in the symbol's print-name component may be the
given string print-name or may be a copy of it, at the implementation's
discretion. The user should not assume that (symbol-name (make-symbol x)) is eq
to x, but also should not alter a string once it has been given as an argument
to make-symbol.
-------------------------------------------------------------------------------
Compatibility note: An implementation might choose, for example, to copy the
string to some read-only area, in the expectation that it will never be
altered.
-------------------------------------------------------------------------------
[Function]
copy-symbol sym &optional copy-props
This returns a new uninterned symbol with the same print name as sym.
[change_begin]
X3J13 voted in March 1989 (COPY-SYMBOL-PRINT-NAME) that the print name of the
new symbol is required to be the same only in the sense of string=; in other
words, an implementation is permitted (but not required) to make a copy of the
print name. User programs should not assume that the print names of the old and
new symbols will be eq, although they may happen to be eq in some
implementations.
[change_end]
If copy-props is non-nil, then the initial value and function definition of the
new symbol will be the same as those of sym, and the property list of the new
symbol will be a copy of sym's.
[change_begin]
X3J13 voted in March 1989 (COPY-SYMBOL-COPY-PLIST) to clarify that only the
top-level conses of the property list are copied; it is as if (copy-list
(symbol-plist sym)) were used as the property list of the new symbol.
[change_end]
If copy-props is nil (the default), then the new symbol will be unbound and
undefined, and its property list will be empty.
[Function]
gensym &optional x
gensym invents a print name and creates a new symbol with that print name. It
returns the new, uninterned symbol.
The invented print name consists of a prefix (which defaults to G), followed by
the decimal representation of a number.
[old_change_begin]
The number is increased by 1 every time gensym is called.
If the argument x is present and is an integer, then x must be non-negative,
and the internal counter is set to x for future use; otherwise the internal
counter is incremented. If x is a string, then that string is made the default
prefix for this and future calls to gensym. After handling the argument, gensym
creates a symbol as it would with no argument. For example:
(gensym) => G7
(gensym "FOO-") => FOO-8
(gensym 32) => FOO-32
(gensym) => FOO-33
(gensym "GARBAGE-") => GARBAGE-34
[old_change_end]
gensym is usually used to create a symbol that should not normally be seen by
the user and whose print name is unimportant except to allow easy distinction
by eye between two such symbols. The optional argument is rarely supplied. The
name comes from ``generate symbol,'' and the symbols produced by it are often
called ``gensyms.''
-------------------------------------------------------------------------------
Compatibility note: In earlier versions of Lisp, such as MacLisp and Interlisp,
the print name of a gensym was of fixed length, consisting of a single letter
and a fixed-length decimal representation with leading zeros if necessary, for
example, G0007. This convention was motivated by an implementation
consideration, namely that the name should fit into a single machine word,
allowing a quick and clever implementation. Such considerations are less
relevant in Common Lisp. The consistent use of mnemonic prefixes can make it
easier for the programmer, when debugging, to determine what code generated a
particular symbol. The elimination of the fixed-length decimal representation
prevents the same name from being used twice unless the counter is explicitly
reset.
-------------------------------------------------------------------------------
If it is desirable for the generated symbols to be interned, and yet guaranteed
to be symbols distinct from all others, then the function gentemp may be more
appropriate to use.
[change_begin]
X3J13 voted in March 1989 (GENSYM-NAME-STICKINESS) to alter the specification
of gensym so that supplying an optional argument (whether a string or a number)
does not alter the internal state maintained by gensym. Instead, the internal
counter is made explicitly available as a variable named *gensym-counter*.
If a string argument is given to gensym, that string is used as the prefix;
otherwise ``G'' is used. If a number is provided, its decimal representation is
used, but the internal counter is unaffected. X3J13 deprecates the use of a
number as an argument.
[Variable]
*gensym-counter*
X3J13 voted in March 1989 (GENSYM-NAME-STICKINESS) to add *gensym-counter*,
which holds the state of the gensym counter; that is, gensym uses the decimal
representation of its value as part of the generated name and then increments
its value.
The initial value of this variable is implementation-dependent but will be a
non-negative integer.
The user may assign to or bind this variable at any time, but its value must
always be a non-negative integer.
[change_end]
[Function]
gentemp &optional prefix package
gentemp, like gensym, creates and returns a new symbol. gentemp differs from
gensym in that it interns the symbol (see intern) in the package (which
defaults to the current package; see *package*). gentemp guarantees the symbol
will be a new one not already existing in the package. It does this by using a
counter as gensym does, but if the generated symbol is not really new, then the
process is repeated until a new one is created. There is no provision for
resetting the gentemp counter. Also, the prefix for gentemp is not remembered
from one call to the next; if prefix is omitted, the default prefix T is used.
[Function]
symbol-package sym
Given a symbol sym, symbol-package returns the contents of the package cell of
that symbol. This will be a package object or nil.
[Function]
keywordp object
The argument may be any Lisp object. The predicate keywordp is true if the
argument is a symbol and that symbol is a keyword (that is, belongs to the
keyword package). Keywords are those symbols that are written with a leading
colon. Every keyword is a constant, in the sense that it always evaluates to
itself. See constantp.
-------------------------------------------------------------------------------